#define FUSE_USE_VERSION  26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

#include "../headers/bib_Comunicacion.h"
#include "../headers/fileSystem.h"
#include "../headers/bib_Estructuras_de_datos.h"
#include "../headers/bib_Abrir_Configuracion.h"
#include "../headers/bib_Log.h"
#include "../headers/bib_Fuse.h"


static int fuse_fat32_getAttr(const char *path, struct stat *stbuf){

	struct tDirEntry archivo;
	char * ruta;

	ruta = (char *)malloc( strlen( path) + 1);

	if( obtenerInfoArchivo( ruta, &archivo))
		return -ENOENT;

	free( ruta);

	asignarAtributos( archivo, stbuf);

	return 0;
}
/*=====================================================================================*/
static int fuse_fat32_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi){

	struct lstDirTable *listaArchivos;
	char * ruta;

	ruta = (char *)malloc( strlen( path) + 1);

	listarPath( ruta, &listaArchivos);

	free( ruta);

	recorrerListaArchivos(listaArchivos, buf, filler);

	liberarListaArchivos(listaArchivos);

	return 0;
}
/*=====================================================================================*/
/*static int fuse_fat32_open(const char *path, struct fuse_file_info *fi){

	struct tDirEntry archivo;

	if (obtenerInfoArchivo(path, &archivo))
		return -ENOENT;

	fs_cache_addfile(fs_cache, path);

	return 0;

}*/
/*=====================================================================================*/
/*static int fuse_fat32_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi){
	struct tDirEntry archivo;
	uint32_t nroCluster;
	uint32_t i;
	size_t respuesta;
	uint32_t *ptr;
	uint32_t primerCluster;
	uint32_t inicio;
	uint32_t cluster;
	char *bufBloque;
	char idBloque;
	uint16_t cant;
	char *buffer;

	if (obtenerInfoArchivo(path, &archivo))
		return -ENOENT;

	nroCluster = convertBytesToClusters(offset);

	if (size + offset > archivo.fileSize){
		size = archivo.fileSize - offset;
		respuesta = size;
	}

	for(i = 0, ptr = ptrFAT + archivo.startFileCluster; i < nroCluster; i++){

		if (i == nroCluster - 1)
			primerCluster = *ptrFAT;

		ptr = ptrFAT + *ptrFAT;
	}

	inicio = TAM_SECTOR * TAM_CLUSTER * (1 - nroCluster) - offset;

	for (cluster = primerCluster, buffer = buf; size != 0; size -= cant){

		getBloque(cluster, &bufBloque, &idBloque);

		if (inicio + size > TAM_CLUSTER * TAM_SECTOR)
			cant = TAM_CLUSTER * TAM_SECTOR - inicio;

		else if (size >= TAM_CLUSTER * TAM_SECTOR)
			cant = TAM_CLUSTER * TAM_SECTOR;

		else
			cant = size;

		memcpy(buffer, bufBloque + inicio, cant);

		liberarIdBuffer(idBloque);
		buf += cant;
		inicio = 0;
	}

	return respuesta;
}*/
/*=====================================================================================*/
/*static int fuse_fat32_truncate(const char *path, size_t size){

	uint32_t nroCluster;
	char *bufBloque;
	char idBloque;
	struct lstDirTable *listaArchivos;
	char *nombreArchivo;
	struct tDirEntry archivo;
	uint32_t cantClustersAct;
	uint32_t nuevaCantClusters;
	uint32_t ultCluster;
	int inicio;
	int longitud;

	recorrerPath(&nroCluster, path);

	getBloque(nroCluster, &bufBloque, &idBloque);

	armarListaArchivos(bufBloque, &listaArchivos);

	liberarIdBuffer(idBloque);

	obtenerNombreDeArchivo(path, nombreArchivo);

	if (buscarArchEnLista(nombreArchivo, listaArchivos, &archivo))
		return -ENOENT;

	liberarListaArchivos(listaArchivos);

	cantClustersAct = convertBytesToClusters(archivo.fileSize);
	nuevaCantClusters = convertBytesToClusters(size);

	if (nuevaCantClusters > cantClustersAct){

		ultClusterArch(archivo.startFileCluster, &ultCluster);

		rmFreeClusterChain(&vectSectoresLibres);

		if ((inicio = archivo.fileSize % (TAM_CLUSTER * TAM_SECTOR))){

			longitud = (TAM_CLUSTER * TAM_SECTOR) - inicio;

			rellenarCluster(ultCluster, inicio, longitud);
		}

		longitud = TAM_SECTOR * TAM_CLUSTER;

		for (i = *(ptrFAT + ultCluster); *(ptrFAT + i) != bsu.EOC; i = *(ptrFAT + i))
			rellenarCluster(ultCluster, 0, longitud);
	}

	else if (nuevaCantCluster < cantClusterAct){

		recorrerXClustersArch(archivo.startFileCluster, nuevaCantClusters, &ultCluster);

		addFreeClusterChain(ultCluster);

		if (((inicio = size % (TAM_CLUSTER * TAM_SECTOR)) && size)){

			longitud = (TAM_CLUSTER * TAM_SECTOR) - inicio;

			rellenarCluster(ultCluster, inicio, longitud);
		}
	}

	else
		if (archivo.fileSize < size)
			if ((inicio = archivo.fileSize % (TAM_CLUSTER * TAM_SECTOR))){

				longitud = (TAM_CLUSTER * TAM_SECTOR) - inicio;

				recorrerXClustersArch(archivo.startFileCluster, nuevaCantClusters, &ultCluster);

				rellenarCluster(ultCluster, inicio, longitud);
			}

	actualizarTamanioArchEnFAT(size, nroCluster, nombreArchivo);

	return 0;
}
*/

static struct fuse_operations fuse_fat32_oper = {
    .getattr  = fuse_fat32_getAttr,
    .readdir  = fuse_fat32_readdir,
  /*  .open     = fuse_fat32_open,
    .read     = fuse_fat32_read,
    .truncate = fuse_fat32_truncate,*/
};



bsUtil bsu;
char *buffer;
char *indiceBuffer;	/*0 bloque libre, 1 bloque ocupado*/
sem_t semBuffer;
pthread_mutex_t mutexIndice;
uint32_t tamBuffer;
CONFIG_EST config;
char nivelLog;
pthread_mutex_t mutexLog;
uint32_t *ptrFAT;
uint8_t *ptrBMP;



int main(int argc, char *argv[]){

    bootSector *bs;
    fsInformationSector *fsInfsector;


    inicializarSemaforos();

    crearMutexLog();

    abrirConfiguracion();

    crearBuffer();

    getBootSector( &bs, &fsInfsector);

    procesarBootSector( &bs, &fsInfsector);

    crearFAT();

    crearBitMap();

    inicializarFATyBitMap();
/*
    delFAT();
    delBitMap();

    liberarBuffer();
*/
	return fuse_main(argc, argv, &fuse_fat32_oper, NULL);
}









